import { each, remove, startsWith } from 'lodash-es';
import { NodeProp } from './enums';
import type { IPlan, IPlanContent } from './interfaces';
import { Node } from './interfaces';

export class PlanService {
  private nodeId = 0;

  public createPlan(
    planName: string,
    planContent: IPlanContent,
    pq: string,
  ): IPlan {
    let planQuery = pq.replace(/(\S)(?!$)(\s{2,})/gm, '$1 ');
    if (!planContent.Plan) {
      throw new Error('Invalid plan');
    }

    const plan: IPlan = {
      id: NodeProp.PEV_PLAN_TAG + new Date().getTime().toString(),
      name: planName || 'plan created on ' + new Date().toDateString(),
      createdOn: new Date(),
      content: planContent,
      query: planQuery,
      ctes: [],
    };

    this.nodeId = 1;
    this.processNode(planContent.Plan, plan);
    return plan;
  }

  public isCTE(node: Node) {
    return (
      node[NodeProp.PARENT_RELATIONSHIP] === 'InitPlan' &&
      startsWith(node[NodeProp.SUBPLAN_NAME], 'CTE')
    );
  }

  public processNode(node: Node, plan: IPlan) {
    node.nodeId = this.nodeId++;
    each(node[NodeProp.PLANS], (child) => {
      if (this.isCTE(child)) {
        plan.ctes.push(child);
      }
      this.processNode(child, plan);
    });

    remove(node[NodeProp.PLANS]!, (child) => {
      return this.isCTE(child);
    });
  }
}
